define(["base"], function(base, Lyx){
    "use strict";

    var log = Lyx.log;
    var cache = {};

    /**
     * 基础ui扩展
     * @exports ui
     * @requires base
     */
    var ui =
    {
        // 获得哪些没有单位的css属性
        noUnit: {},
        $noUnit: {
            get: function(noUnit, getValue)
            {
                Lyx.each("zIndex fontWeight opacity widows orphans fillOpacity \
                columnCount order flexGrow flexShrink".split(" "), function(index, name){
                    noUnit[name] = true;
                });
                return getValue(noUnit);
            }
        },

        // 获得所有的style属性
        style: {},
        $style: {
            get: function(style, getValue)
            {
                for(var i in ui.$("body[0]").style)
                {
                    if(isNaN(parseInt(i)))
                    {
                        style[i] = "";
                    }
                }
                return getValue(style);
            }
        },

        funcList: [],
        /**
         * onload事件收集器
         * @example
         * ui.onload = function(){
         *     console.log("1. onload.....")
         * };
         * ui.onload = function(){
         *     console.log("2. onload.....")
         * };
         * // 1. onload.....
         * // 2. onload.....
         * // 多次赋值的函数都会被执行，并不会产生冲突
         */
        onload: null,
        $onload: {
            set: function(value)
            {
                ui.funcList.push(value);
            }
        }
    };

    Lyx.observe(ui);

    /**
     * 表达式选择器
     * #id
     * .class
     * element
     * 
     * 基本语法：
     * selector[index]		具体索引位置
     * selector[begin:end] 	具体分片
     * selector[:end]		结尾分片 
     * selector[begin:]		起始分片
     * selector				全部
     * @param {string} selector 选择表达式
     * @param {element} [el = document] 执行选择表达式的元素
     * @returns {element[] || element} 具体索引位置或者通过id选择的结果返回指定元素，其它情况返回数组集合
     */
    ui.$ = function(selector, el)
    {
        if(Lyx.type(selector) != "string")
        {
            return selector;            
        }
        try
        {
            syntaxCheck(selector)
        }
        catch(error)
        {
            log(error.log + "\n" + error.stack, "error")
            return;
        }
        el = [el || document];
        var tagNameList = selector.split(/ /);
        var scope, tagName;

        Lyx.each(tagNameList, function(index, name){
            scope = name.match(/\[(\d+|)(:|)(|\d+)\]$/);
            tagName = name.replace(/\[(\d+|)(:|)(|\d+)\]$/, "");
            var list = [];
            Lyx.each(el, function(index, el){
                var childList = el.querySelectorAll(tagName);
                if(scope)
                {
                    var begin = isNaN(parseInt(scope[1])) ? undefined : parseInt(scope[1]);
                    var end = isNaN(parseInt(scope[3])) ? undefined : parseInt(scope[3]);
                    if(scope[2] == "")
                    {
                        end = begin + 1;
                    }
                    list = list.concat(ui.NodeListToArray(childList).slice(begin, end));
                }
                else
                {
                    list = list.concat(ui.NodeListToArray(childList));
                }
            });
            el = list;
            if(list.length == 0)
            {
                return false;
            }
        });
        if(tagName[0] == "#" || (scope != null && scope[2] == "") && el.length !=0)
        {
            return el[0];
        }
        else
        {
            return el;
        }
    }

    /**
     * 取消冒泡和默认事件
     * @param {event} event 
     */
    ui.stop = function(event)
    {
        if(event.stopPropagation)
        {
            // 取消冒泡
            event.stopPropagation();
        }
        else
        {
            event.cancelBubble = true;
        }

        if(event.preventDefault)
        {
            // 取消默认行为
            event.preventDefault();
        }
        else
        {
            event.returnValue = false;
        }
    }

    /**
     * 设置元素style样式
     * @param {element[]} el 操作对象
     * @param {object} obj style样式类
     */
    ui.css = function(list, obj)
    {
        if(typeof(list) == "string")
        {
            list = [ui.$(list)];
        }
        else if(!Lyx.isArrayLike(list))
        {
            list = [list];
        }
        Lyx.each(list, function(index, el){
            Lyx.each(obj, function(name, value){
                el.style[name] = defaultUnit(name, value);
            });
        });
    }

    /**
     * 动态插入节点
     * @param {element} el 定位元素
     * @param {string} element 插入节点类型
     * @param {string} place 相对于定位元素的位置
     * @param {object} obj 插入节点绑定属性
     * @returns {element} 新建的结点
     */
    ui.addNode = function(el, tagName, place, obj)
    {
        var node = document.createElement(tagName);
        Lyx.each(obj, function(name, value){
            if(name == "style")
            {
                ui.css(node, value);
            }
            else
            {
                node.setAttribute(name, value);
            }
        });
        switch(place)
        {
            case "innerFirst": el.insertBefore(node, el.firstChild); break;
            case "before": el.parentNode.insertBefore(node, el); break;
            case "innerEnd": el.appendChild(node); break;
            default: break;
        }
        return node;
    }


    /**
     * @constructor
     * @memberof module:ui~
     * @param {string} log 错误日志
     */
    function syntaxError(log)
	{
		this.log = log;
		this.stack = (new Error()).stack;
	}


    /**
     * 检查该属性是否需要单位，如果需要且没有写就会添加上单位
     * @memberof module:ui~
     * @param {string} name 属性名
     * @param {string | number} value 属性值
     * @returns {string | number} 处理后的数据
     */
    function defaultUnit(name, value)
    {
        if(!ui.noUnit[name])
        {
            var type = Lyx.type(value);
            if(type == "string")
            {
                return value + (parseInt(value) == value + "" ? "px" : "");
            }
            else if(type == "number")
            {
                return value + "px";
            }
        }
        else
        {
            return value;
        }
    }

    /**
     * @memberof module:ui~
     * @param expression 要检查的表达式
     * @param syntax 语法格式
     */
	function syntaxCheck(expression)
    {
        if(expression.length != expression.trim().length)
        {
            log("表达式前后不应该有空格", "error");
            return false;
        }

        var list = expression.split(/ /);
        Lyx.each(expression.split(/ /), function(index, name){
            var result = name.match(/\[(\d+|)(:|)(|\d+)\]$/);
            if(result != null && result[0] == "[]")
            {
                throw new syntaxError("不允许出现空索引：" + name);
            }

            if(name[0] == "#")
            {
                if(index != 0)
                {
                    throw new syntaxError("只允许id查找器出现在第一位");
                }
                
                if(result != null && /\[[0-9]*\]/.test(result[0]))
                {
                    throw new syntaxError("id查找时不允许索引操作：" + name);
                }
            }
        });
	}

    // 获得计算之后的css属性
    ui.getFinalStyle = function(el)
    {
        return el.currentStyle ? el.currentStyle : document.defaultView.getComputedStyle(el, null);
    };

    // 新构造的数组需要给每一个节点添加css成员函数
    ui.NodeListToArray = function(nodeList)
    {
        return [].slice.call(nodeList);
    };

    // 带单位的数据会自动处理为数字
    ui.getStyle = function(el)
    {
        if(typeof el == "string")
        {
            el = ui.$(el)
        }
        var style = {};
        var finalStyle = ui.getFinalStyle(el);
        Lyx.each(ui.style, function(name, value){
            style[name] = finalStyle[name];
            style["$" + name] = {
                set: function(value)
                {
                    ui.css(el, {
                        [name]: value
                    });
                },
                get: function()
                {
                    var value = parseInt(finalStyle[name]);
                    return isNaN(value) ? finalStyle[name] : value;
                }
            }
        });
        Lyx.observe(style);
        return style;
    }

    /**
     * 获取可视窗口高度
     * @returns {Number}
     */
    ui.getWindowHeight = function()
    {
        var windowHeight = 0;
        if(document.compatMode == "CSS1Compat")
        {
            windowHeight = document.documentElement.clientHeight;
        }
        else
        {
            windowHeight = document.body.clientHeight;
    　　}
        return windowHeight;
    }

    /**
     * 获取body滚动条位置
     * @returns {Number}
     */
    ui.getScrollTop = function()
    {
        var scrollTop = 0;
        if(document.documentElement && document.documentElement.scrollTop)
        {
            scrollTop = document.documentElement.scrollTop;
        }
        else if(document.body)
        {
            scrollTop = document.body.scrollTop;
        }
        return scrollTop;
    }

    /**
     * 兼容浏览器获取event事件
     * @returns
     */
    ui.getEvent = function(args)
    {
        var event = args[args.length - 1];
        if(event.target && event.clientX && event.clientY) 
        {
            return event;
        }
        else
        {
            return window.event;
        }
    }

    /**
    ** 设置body滚动条位置
    **/
    ui.setScrollTop = function(top)
    {
        if(document.documentElement && document.documentElement.scrollTop)
        {
            document.documentElement.scrollTop = top;
        }
        else if(document.body)
        {
            document.body.scrollTop = top;
        }
    }

    /**
     * 返回浏览器版本，如果是IE会带上版本号
     * @returns {String}
     */
    ui.myBrowser = function()
    {
        var userAgent = navigator.userAgent;				// 取得浏览器的userAgent字符串
        var isOpera = userAgent.indexOf("Opera") > -1;		// 判断是否Opera浏览器
        var isIE = userAgent.indexOf("compatible") > -1 &&
            userAgent.indexOf("MSIE") > -1 && !isOpera; 	// 判断是否IE浏览器
        var isFF = userAgent.indexOf("Firefox") > -1; 		// 判断是否Firefox浏览器
        var isSafari = userAgent.indexOf("Safari") > -1;	// 判断是否Safari浏览器
        var isChrome = userAgent.indexOf("Chrome") > -1;	// 判断是否Chrome浏览器
        if(isIE)
        {
            var IE5 = IE55 = IE6 = IE7 = IE8 = false;
            var reIE = new RegExp("MSIE (\\d+\\.\\d+);");
            reIE.test(userAgent);
            var fIEVersion = parseFloat(RegExp["$1"]);
            IE55 = fIEVersion == 5.5;
            IE6 = fIEVersion == 6.0;
            IE7 = fIEVersion == 7.0;
            IE8 = fIEVersion == 8.0;
            return "IE" + fIEVersion
        }
        switch(true)
        {
            case isOpera: return "Opera";
            case isFF: return "Firefox";
            case isSafari: return "Safari";
            case isChrome: return "Chrome";
            case true: return "none";
        }
    }
    
    /** 为元素添加句柄事件 */
    ui.hander =
    {
        add: function(el, type, handler, useCapture)
        {
            useCapture = useCapture || false;
            el.addEventListener(this.compatibility(type), handler, useCapture);
        },
        remove: function(el, type, handler, useCapture)
        {
            useCapture = useCapture || false;
            el.removeEventListener(this.compatibility(type), handler, useCapture);
        },
        compatibility: function(type)
        {
            if(ui.myBrowser() == "Firefox")
            {
                if(type == "mousewheel")
                {
                    return "DOMMouseScroll";
                }
            }
            if(type == "transitionend")
            {
                return ui.whichTransitionEvent();
            }
            return type;
        }
    };

    /* 获取不同浏览器的transition名称 */
    ui.whichTransitionEvent = function()
    {
        var el = document.createElement('fakeelement');
        var transitions = 
        {
            'transition': 'transitionend',
            'OTransition': 'oTransitionEnd',
            'MozTransition': 'transitionend',
            'WebkitTransition': 'webkitTransitionEnd'
        }
        for(var i in transitions)
        {
            if(el.style[i] !== undefined)
            {
                return transitions[i];
            }
        }
    }

    /** 
     * 创建websocket连接
     * 可为实例定义onopen、onmessage、onclose事件
     * @constructor
     * @param {string} url 连接地址
     */
    ui.websocket = Lyx.createClass(function(p2t){
        /**
         * 初始化websocket
         * @memberof module:ui.websocket.prototype
         */
        p2t.init = function(url)
        {
            var self = this;

            /** websocket是否已经打开 */
            this.open = false;

            /** 数据发送队列，在连接未打开时，暂存发送数据 */
            this.sendQueue = new Lyx.queue();

            /** 连接地址 */
            this.url = url;

            if ('WebSocket' in window)
            {
                /** websocket连接主体 */
                this.ws = new WebSocket(this.url);
            }
            else if ('MozWebSocket' in window)
            {
                this.ws = new MozWebSocket(this.url);
            }
            else
            {
                alert('您的浏览器不支持websocket！');
                return;
            }
            this.ws.onopen = function()
            {
                try
                {
                    self.open = true;
                    self.onopen();
                    while(self.sendQueue.length != 0)
                    {
                        self.send(self.sendQueue.dequeue());
                    }
                }
                catch(error)
                {
                    log(error);
                }
                
            };
            this.ws.onmessage = function(event)
            {
                try
                {
                    self.onmessage(event);
                }
                catch(error)
                {
                    console.error(error);
                }
            };
            this.ws.onclose = function()
            {
                try
                {
                    self.open = false;
                    self.onclose();
                }
                catch(error)
                {
                    log(error);
                }
            }
        }

        /**
         * 发送数据
         * @memberof module:ui.websocket.prototype
         */
        p2t.send = function(data)
        {
            if(this.open)
            {
                this.ws.send(data);
            }
            else
            {
                this.sendQueue.enqueue(data);
            }
        }

        /**
         * 关闭websocket连接
         * @memberof module:ui.websocket.prototype
         */
        p2t.close = function()
        {
            this.ws.close();
        }
    });

    window.onload = function()
    {
        Lyx.each(ui.funcList, function(index, load){
            load();
        });
    }

	return ui;
});